package com.pocket.insight.base.utils;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSON;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.serializers.ClosureSerializer;
import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.objenesis.strategy.InstantiatorStrategy;
import org.springframework.objenesis.strategy.StdInstantiatorStrategy;

import java.lang.invoke.SerializedLambda;
import java.util.Arrays;
import java.util.List;

/**
 * 描述：
 *
 * @author shuize
 * @create 2024/12/10
 */
@Slf4j
public class SerializationUtils {

    private static final ThreadLocal<Kryo> kryoCache = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        kryo.setRegistrationRequired(false);
        kryo.setCopyReferences(true);
        kryo.setOptimizedGenerics(false);
        kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy((InstantiatorStrategy) new StdInstantiatorStrategy()));
        kryo.register(Object[].class);
        kryo.register(Class.class);
        kryo.register(SerializedLambda.class);
        kryo.register(ClosureSerializer.class, new ClosureSerializer());
        return kryo;
    });


    public static <T> T deepCopy(T other) {
        try {
            return (kryoCache.get()).copy(other);
        } catch (KryoException var2) {
            KryoException e = var2;
            log.error(e.getMessage(), e);
            assert e.getMessage().contains("missing no-arg constructor");
            return null;
        }
    }

    public static <T> List<T> deepCopyArray(List<T> other, Class<T> clazz) {
        try {
            return kryoCache.get().copy(other);
        } catch (KryoException var4) {
            KryoException e = var4;
            log.error(e.getMessage(), e);
            assert e.getMessage().contains("missing no-arg constructor");
            Class<?> aClass = other.getClass();
            return aClass.isAnonymousClass() ? jsonDeepCopyArray(other, clazz) : null;
        }
    }

    public static <T> List<T> jsonDeepCopyArray(List<T> other, Class<T> clazz) {
        return other == null ? null : toJavaObjectArray(toJSONString((Object)other), clazz);
    }

    public static <T> List<T> toJavaObjectArray(String json, Class<T> clazz) {
        return StringUtils.isBlank(json) ? null : JSON.parseArray(json, clazz);
    }

    public static String toJSONString(Object object) {
        if (object == null) {
            return "";
        } else {
            return object instanceof String ? (String)object : JSON.toJSONString(object, Arrays.toString(new SerializerFeature[]{SerializerFeature.DisableCircularReferenceDetect}));
        }
    }

    public static <T> T toJavaObject(String json, Class<T> clazz) {
        return StringUtils.isBlank(json) ? null : JSON.parseObject(json, clazz);
    }

}
